import { _decorator, Component, Enum, Node } from 'cc';
import { UIContianer } from './UIContianer';
import { UIUtils } from './UIUtils';
import { UIManager } from './UIManager';
import { UIWatcher } from './UIWatcher';
import { UIAnimationType } from '../NeedToChange/UIConifig';
import { UIAnimation } from './UIAnimation';
import { BundleConfig } from '../NeedToChange/BundleConfig';
const { ccclass, property } = _decorator;

@ccclass('UIBase')
export class UIBase extends Component {
    //应该有一个容器专门存储查找节点和组件
    protected _uiContainer:UIContianer = new UIContianer();
    //是否在关闭的时候要销毁
    protected _isDestroy:boolean = false;
    get isDestroy(){
        return this._isDestroy;
    }
    set isDestroy(destroy:boolean){
        this._isDestroy = destroy;
    }

    private _uiName:string ='';
    get uiName(){
        return this._uiName;
    }
    set uiName(uiName:string){
        this._uiName = uiName;
    }

    //存储监听者
    private _arrWatcher:UIWatcher[] = [];
    @property({type:Enum(UIAnimationType),displayName:'入场动画',tooltip:'入场退场动画,fade淡入淡出...'})
    animType:UIAnimationType = UIAnimationType.none;
    private _uiAnimation:UIAnimation = null;
    //ui的初始化接口，只初始化一次。第一次打开的时候调用。
    //只写在基类，然后另外再写一个初始化接口让派生类重写。
    //公共的初始化逻辑
    init(...rest:any[]){
        //UI激活之后，去搜索当前UI的整个节点树，然后把需要关注的存储到当前UI下的uiContainer容器中。
        UIUtils.findNode(this.node,this._uiContainer);
        this._uiAnimation = new UIAnimation(this);
        this.onInit.apply(this,arguments);
    }

    //派生类重写的初始化接口
    onInit(...rest:any[]){

    }

    //打开接口。
    open(...rest:any[]){
        //显示出ui
        if(!this.node.active){
            this.node.active = true;
        }
        //播放入场动画，播放完毕后，在处理每次入场逻辑。
        this._uiAnimation.playAnimtion('open',this.animType,()=>{
            //处理每次进来的逻辑。
            this.onEnter.apply(this,arguments);
        });
        
        
    }
    //关闭接口
    close(...rest:any[]){
        //UI退出（派生类）
        this.onExit.apply(this,arguments);
        this._uiAnimation.playAnimtion('close',this.animType,()=>{
            
            if(this._isDestroy){
                //删除掉跟当前ui的所有wachter从对应的dep删掉。
                for(let watcher of this._arrWatcher){
                    watcher.removeSelf();
                }
                this.node.destroy();
                return;
            }
            if(this.node.active){
                this.node.active = false;
            }
        });
        
    }

    //每次进来 让派生类重写。
    onEnter(...rest:any[]){

    }
    //每次退出。
    onExit(...rest:any[]){

    }

    /**
     * 
     * @param uiName 要打开的ui名字
     * @param isClose 当前ui是否要关闭
     * @param isDestroy 这个ui如果要关闭，是否要销毁
     * @param layerName 挂哪个层
     * @param rest 携带的数据
     */
    openUI(uiName:string,isClose:boolean = false,isDestroy:boolean=false,bundleName?:string,layerName:string='Normal',...rest:any[]){
        let args = [];
        for(let value of rest){
            args.push(value);
        }
        // unshift:数组前部插入数据，shift前部删除
        // push                     pop
        if(isClose){
            let temp = UIUtils.deepClone(args);
            temp.unshift(isDestroy);
            temp.unshift(this.uiName);            
            this.closeUI.apply(this,temp);
        }
        //要打开的ui的层跟ui名字，额外的数据。
        bundleName = bundleName||BundleConfig.UI.name;
        args.unshift(layerName);
        args.unshift(bundleName);
        args.unshift(uiName);
        UIManager.instance.openUI.apply(UIManager.instance,args);
    }

    closeUI(uiName:string,isDestroy:boolean= false,...rest:any[]){
        UIManager.instance.closeUI.apply(UIManager.instance,arguments);
    }

    closeSelf(isDestroy:boolean = false,...rest:any[]){
        let args = [];
        args.push(this.uiName);
        for(let value of Array.from(arguments)){
            args.push(value);
        }
        this.closeUI.apply(this,args);
    }


    getNode(nodeName:string){
        return this._uiContainer.getNode(nodeName);
    }
    getComp<T>(nodeName:string,compTypeName:string):T{
        return this._uiContainer.getComp(nodeName,compTypeName) as T;
    }
    // 封装事件注册，以后用起来更方便一些。
    addEventListener(eventName:string,nodeName:string,cb:Function){
        //获取节点
        let node = this.getNode(nodeName);
        if(!node){
            return;
        }
        node.on(eventName,cb,this);
    }

    //点击
    addClickEventListener(nodeName:string,cb:Function){
        this.addEventListener('click',nodeName,cb);
    }
    /**
     * 
     * @param msgName 响应的消息，函数名字
     * @param uiName 响应的ui，如果空字符串或者传递空那么认为所有的ui都会接受到。
     * @param rest 
     */
    sendMsg(msgName:string,uiName:string,...rest:any[]){
        UIManager.instance.sendMsg.apply(UIManager.instance,arguments);
    }
    
    //供派生类重写，触发默认响应。
    handleMsg(...rest:any[]){

    }


    //绑定回调。
    bindCb(data:object,key:string,cb:Function,target?:any,comp?:Component){
        target = target||this;
        let watcher = new UIWatcher(data,key,target,cb,comp);
        //存储起来的目的：为了后续如果ui销毁，要把这个watcher从对应dep中删掉。
        this._arrWatcher.push(watcher);
    }


    //绑定组件
    bindComp(data:Object,key:string,comp:Component,target?:any){
        this.bindCb(data,key,UIUtils.refreshComp,target,comp);
    }
}


